import { configByID, gameConfig, gameConfigHandle, propName } from "js/config/gameConfig"
import utils from "js/core/utils"
import { EffectModel, FighterAttriModel, FighterModel, SkillModel } from "js/model/fighterModel"
import { PartnerModel } from "js/model/partnerModel"
import treasureHandle from "./treasureHandle"
import equipmentHandle from "./equipmentHandle"
import { PlayerModel } from "js/model/playerModel"
import { ItemModel } from "js/model/itemModel"
import { PosAttriLvlModel } from "js/model/formationModel"


class FighterHandle {

    calcFormation(player, fighter: FighterModel) {
        if (fighter) {
            let active = player.formation.active
            let lvl = player.formation.lvls[active] || 1
            let formationId = gameConfig.baseFormation.list[active]
            let formation = gameConfigHandle.configByID[formationId]
            let pos = fighter.formationPos
            if (pos != null && pos != undefined) {
                let matchPos
                for (let i = 0; i < formation.posAttris.length; i++) {
                    let posAttris = formation.posAttris[i];
                    let match = posAttris.pos.findIndex(i => i == pos) != -1
                    if (match) {
                        matchPos = posAttris
                        break
                    }
                }
                if (matchPos) {
                    matchPos.attris.forEach(attri => {
                        let name = attri[0]
                        let values = attri[1]
                        let isPer = utils.getPerByAttri(name) == '%'
                        let key = isPer ? name.replace('Per', '') : name

                        if (isPer) {
                            if (key == 'attack' || key == 'maxHp' || key == 'def') {
                                fighter.attri[key] += Math.floor(fighter.attri[key] * utils.getIncValue(values, lvl - 1) / 100)
                            } else {
                                fighter.attri[key] += utils.getIncValue(values, lvl - 1)
                            }
                        } else {
                            fighter.attri[key] += Math.floor(fighter.attri[key] * utils.getIncValue(values, lvl - 1) / 100)
                        }
                    })
                }
            }
        }
    }

    calcTreasure(partner: PartnerModel, fighter: FighterModel) {
        let lvls = partner.treasure.posLvls
        let posUpAttriValues = gameConfig.treasure.posUpAttriValues
        let posUpAttriNames = gameConfig.treasure.posUpAttriNames
        let suit = {}
        Object.entries(partner.treasure.items).forEach((it, i) => {
            let part = it[0]
            let item: any = it[1]
            if (item) {
                let item: any = it[1]
                if (item) {
                    let itemConfig = gameConfigHandle.configByID[item.tID]
                    let posUpName = posUpAttriNames[itemConfig.part - 1]
                    let posValues = posUpAttriValues[itemConfig.part - 1]
                    let lvl = lvls[itemConfig.part] || 0
                    // 计算属性加成
                    let attriValues = treasureHandle.calcTreasureAttri(item)
                    Object.entries(attriValues).forEach(av => {
                        let name = av[0]
                        let value: any = av[1]
                        if (name.indexOf('skill_') != -1) {
                            let skillID = name.replace("skill_", "")
                            if (skillID == 'all') {
                                fighter.skills.map(s => {
                                    s.skillLvl += value
                                })
                            } else {
                                fighter.skills.filter(s => s.skillID == Number(skillID)).map(s => {
                                    s.skillLvl += value
                                })
                            }
                        } else {
                            let isPer = utils.getPerByAttri(av[0])
                            let up = utils.getIncValue(posValues, lvl)
                            if (isPer) {
                                fighter.attri[name] = (fighter.attri[name] || 0) + utils.getValueByAttri(value * (1 + up / 100), av[0])
                            } else {
                                fighter.attri[name] = (fighter.attri[name] || 0) + utils.getValueByAttri(isPer == '%' ? value + up : value * (1 + up / 100), av[0])
                            }
                        }
                    })
                    // 判断套装
                    let suitID = itemConfig.suitID
                    let upLvl = item.treasure.upLvl || 0
                    if (suitID) {
                        if (suit[suitID]) {
                            suit[suitID]['putOn'] += 1
                        } else {
                            let config = gameConfig.suit.all[suitID]
                            suit[suitID] = { putOn: 1, config, upLvls: { 1: 0, 2: 0, 3: 0 } }
                        }
                        if (upLvl) {
                            suit[suitID].upLvls[upLvl] += 1

                            if (upLvl == 2) {
                                suit[suitID].upLvls[1] += 1
                            } else if (upLvl == 3) {
                                suit[suitID].upLvls[2] += 1
                                suit[suitID].upLvls[1] += 1
                            }
                        }
                    }
                }
            }
        })
        Object.entries(suit).forEach(s => {
            let suitID = s[0]
            let item: any = s[1]
            let lvl = 0
            for (let i = 1; i <= 3; i++) {
                let count = item.upLvls[i]
                if (count >= 4) {
                    lvl = i
                }
            }
            if (item.putOn >= item.config.activeNum) {
                Object.entries(item.config.attri).forEach(attri => {
                    let key = attri[0]
                    let values: any = attri[1]
                    let value = utils.getIncValue(values, lvl)
                    let isPer = utils.getPerByAttri(attri[0]) == '%'
                    if (isPer) {
                        key = key.replace('Per', '')
                        fighter.attri[key] += Math.floor(fighter.attri[key] * value / 100)
                    } else {
                        fighter.attri[key] += value
                    }
                })
            }
        })
    }

    calcSkill(fighter: FighterModel) {
        let skills = fighter.skills
        for (let i = 0; i < skills.length; i++) {
            let skill = skills[i]
            let skillID = skill.skillID
            let skillLvl = skill.skillLvl || 1
            let skillConfig = gameConfigHandle.configByID[skillID]
            if (Array.isArray(skillConfig.cd)) {
                let jjLvl = this.getSkillLvl(skill.skillLvl)
                skill.cd = utils.getIncValue(skillConfig.cd, jjLvl)
            } else {
                skill.cd = skillConfig.cd
            }
            if (skillConfig.triggers) {
                skillConfig.triggers.forEach(triggerItem => {
                    if (skillLvl >= triggerItem.limitLvl || !triggerItem.limitLvl) {
                        let trigger = new EffectModel({
                            skillID: skillID,
                            type: triggerItem.triggerType,
                            skillLvl: skillLvl,
                            data: JSON.parse(JSON.stringify(triggerItem))
                        })
                        if (!fighter.effects[triggerItem.triggerType]) {
                            fighter.effects[triggerItem.triggerType] = []
                        }
                        fighter.effects[triggerItem.triggerType].push(trigger)
                    }
                })
            }
            let cd = skill.cd
            skill.cd = utils.floor(cd * (100 - skill.cdPer) / 100)
            //出招属性降低技能CD
            let reduceSkillCd = fighter.attri.reduceSkillCd
            // skill.cd -= reduceSkillCd * 50
            let skillsReduceCd = fighter.skillsReduceCd
            if (skillsReduceCd[skillID]) {
                skill.cd -= skillsReduceCd[skillID] * 1000
            }
        }
    }

    calcBattleFighterAttri(fighter: FighterModel) {
        let hp = fighter.battleAttri?.hp || 0
        let shield = fighter.battleAttri?.shield || 0
        let battleAttri = new FighterAttriModel(fighter.attri)

        //百分比提升属性
        let jcAttriNames = gameConfigHandle.gameConfig.partner.attrisJc
        let jcAttriPerNames = gameConfigHandle.gameConfig.partner.attriPers
        for (let i = 0; i < jcAttriNames.length; i++) {
            let attriName = jcAttriNames[i]
            let attriNum = battleAttri[attriName]
            let attriPerNum = battleAttri[jcAttriPerNames[i]]
            battleAttri[attriName] = Math.floor(attriNum * (100 + attriPerNum) / 100)
            battleAttri[jcAttriPerNames[i]] = 0
        }
        //buff
        fighter.status = {}
        fighter.buffs.forEach(buff => {
            let buffConfig = gameConfigHandle.configByID[buff.buffID]
            let buffLvl = buff.lvl || 1
            let stack = buff.stack || 1
            if (buffConfig.attris) {
                Object.entries(buffConfig.attris).forEach(attriItem => {
                    let attriName = attriItem[0]
                    let attriValues: any = attriItem[1]
                    let aName = attriName.replace('Per', '')
                    let isPer = utils.getPerByAttri(attriName) == '%'
                    if (attriName == 'reduceDefPer') {
                        battleAttri.def = battleAttri.def * (1 - utils.getIncValue(attriValues, buffLvl - 1) / 100)
                        if (battleAttri.def <= 0) {
                            battleAttri.def = 1
                        }
                    } else if (attriName == 'attackSpeedPer') {
                        battleAttri.attackSpeed = battleAttri.attackSpeed * (1 + utils.getIncValue(attriValues, buffLvl - 1) / 100)
                        if (battleAttri.attackSpeed <= 0) {
                            battleAttri.attackSpeed = 1
                        }
                    } else {
                        if (isPer) {
                            if (aName == 'reduceHurt') {
                                battleAttri[aName] = utils.getIncValue(attriValues, buffLvl - 1)
                            } else {
                                battleAttri[aName] += (utils.getIncValue(attriValues, buffLvl - 1) / 100 * battleAttri[aName])
                            }
                        } else {
                            battleAttri[attriName] += utils.getIncValue(attriValues, buffLvl - 1) * stack
                        }
                    }
                })
            }
            fighter.status[buffConfig.buffType] = true
        })
        //百分比提升属性
        for (let i = 0; i < jcAttriNames.length; i++) {
            let attriName = jcAttriNames[i]
            let attriNum = battleAttri[attriName]
            let attriPerNum = battleAttri[jcAttriPerNames[i]]
            battleAttri[attriName] = Math.floor(attriNum * (100 + attriPerNum) / 100)
        }
        //汇总
        fighter.battleAttri = battleAttri
        fighter.battleAttri.hp = hp
        fighter.battleAttri.shield = shield
        // fighter.battleAttri.hurtType = fighter.attri.hurtType
    }

    calcPower(partner: PartnerModel, fighter: FighterModel) {
        let fcOfAttris = gameConfigHandle.gameConfig.partner.fcOfAttris
        let totalPower = 0
        Object.entries(fcOfAttris).forEach(item => {
            let fAttriName = item[0]
            let fValue = Number(item[1])
            if (fighter.battleAttri[fAttriName]) {
                totalPower += fighter.battleAttri[fAttriName] * fValue
            }
        })
        let equipmentsOn = partner.equipments[partner.equipmentActive] || []
        Object.entries(equipmentsOn).forEach(equipment => {
            totalPower += equipmentHandle.getFcOfEquipment(equipment[1])
        })
        fighter.power = Math.floor(totalPower)
    }

    calcQualityAddAttri(fighter: FighterModel, key: string, value: number) {
        let addPer = utils.getIncValue(gameConfig.partner.qualityAddAttriPer, fighter.quality)
        if (gameConfig.partner.baseAttri[key]) {
            value = value * (1 + addPer / 100)
        }
        return value
    }

    getSkillLvl(skillLvl: number) {
        let jjLvl = Math.floor((skillLvl - 1) / 10) + 1
        return jjLvl
    }


    calcCdHurtPer(cd, cdAddHurt1, cdAddHurt2) {
        cd = Math.floor(cd / 500)
        let values = [2, 2, 0.6 + cdAddHurt2, 0, 'floor']
        let cdHurtPer = Math.pow(cdAddHurt1, cd) * 100 - 100
        if (cd >= 16) {
            cdHurtPer += utils.getIncValue(values, cd - 16)
        }
        return cdHurtPer
    }

    calcTotalPower(player: PlayerModel) {
        let totalPower = 0
        player.teamList.list.forEach(p => {
            totalPower += p && p.fighter.power || 0
        })
        return totalPower
    }

    calcTitles(player: PlayerModel, fighter: FighterModel) {
        let values = {}
        let list = []
        let infos = player.titleInfo?.infos || {}
        Object.entries(infos || []).forEach(i => {
            let id = i[0]
            let config = gameConfigHandle.configByID[id]
            if (config) {
                Object.entries(config.effect).forEach(e => {
                    let name = e[0]
                    if (name == 'attri') {
                        list.push(e[1])
                    }
                })
            }
        })
        list.forEach(l => {
            Object.entries(l).forEach(entry => {
                let name = entry[0]
                let value = entry[1]
                if (!values[name]) {
                    values[name] = 0
                }
                values[name] += Number(value)
            })
        })
        const attriList = ['maxHp', "attack", 'def', "hit", "dodge", "crit", 'critHurt', "attackSpeed", "recoverHp"]
        let attriAddList = {}
        Object.entries(values).forEach(entry => {
            let attriName = entry[0]
            let value: any = entry[1]
            if (attriName == 'allAttriPer') {
                attriList.forEach(a => {
                    if (!attriAddList[a]) {
                        attriAddList[a] = 0
                    }
                    attriAddList[a] += Number(value)
                })
            } else {
                let name = attriName.replace('Per', '')
                if (!attriAddList[name]) {
                    attriAddList[name] = 0
                }
                attriAddList[name] += Number(value)
            }
        })
        Object.entries(attriAddList).forEach(entry => {
            let attriName = entry[0]
            let value: any = Number(entry[1])
            if (!fighter.attri[attriName]) {
                fighter.attri[attriName] = 0
            }
            if (attriName == 'recoverHp') {
                fighter.attri[attriName] += Number(value)
            } else {
                let v = fighter.attri[attriName] * value / 100
                if (utils.getPerByAttri(attriName)) {
                    v = Number(v.toFixed(1))
                } else {
                    v = Math.floor(v)
                }
                fighter.attri[attriName] += Number(v)
            }
        })
    }

    calcPosAttri(player: PlayerModel, partner: PartnerModel, fighter: FighterModel) {
        let attri = player.formation.posAttri[partner.formationPos]
        if (attri) {
            if (!player.formation.posAttriLvl) {
                player.formation.posAttriLvl = new PosAttriLvlModel({})
            }
            let lvl = player.formation.posAttriLvl[attri] || 0
            let values = gameConfig.baseFormation.newFormation[attri]
            if (!values) {
                values = gameConfig.baseFormation.newFormation.baseValues
            }
            if (attri == 'reduceSkillCd' && lvl) {
                let value = utils.getIncValue(values, lvl, true)
                let cd = fighter.skillsReduceCd[fighter.skills[0].skillID] || 0
                fighter.skillsReduceCd[fighter.skills[0].skillID] = (cd + value)
            } else if (lvl) {
                let value = utils.getIncValue(values, lvl)
                value = (fighter.attri[attri] || 0) * value / 100
                fighter.attri[attri] += utils.getPerByAttri(attri) == '%' ? Number(value.toFixed(1)) : Math.floor(value)
            }
        }
    }
}

let fighterHandle = new FighterHandle()
export default fighterHandle